package com.bjtct.plugin.autogen.wizards;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.DialogSettings;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWizard;

import com.bjtct.plugin.autogen.TctConsole;
import com.bjtct.plugin.autogen.db.ColumnWrap;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * This is a sample new wizard. Its role is to create a new file resource in the
 * provided container. If the container resource (a folder or a project) is
 * selected in the workspace when the wizard is opened, it will accept it as the
 * target container. The wizard creates one file with the extension "mpe". If a
 * sample multi-page editor (also available as a template) is registered for the
 * same extension, it will be able to open it.
 */

public class AutoGenWizard extends Wizard implements INewWizard {
	private DataSourcePage ds;
	private TableDetailSettingPage ts;
	private GenCodePathPage gcpp;
	private ISelection selection;
	private DialogSettings dset;
	private static Configuration cfg = null;

	static {
		cfg = new Configuration();
		 cfg.setClassForTemplateLoading(AutoGenWizard.class, "/conf");
		/*try {
			cfg.setDirectoryForTemplateLoading(new java.io.File("d:\\conf"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
		cfg.setDefaultEncoding("UTF-8");
	}

	/**
	 * Constructor for AutoGenWizard.
	 */
	public AutoGenWizard() {
		super();
		dset = new DialogSettings("autogen");
		setNeedsProgressMonitor(true);
	}

	@Override
	public void createPageControls(Composite pageContainer) {
		// TODO Auto-generated method stub
		// super.createPageControls(pageContainer);
	}

	@Override
	public IDialogSettings getDialogSettings() {

		return dset;
	}

	/**
	 * Adding the page to the wizard.
	 */

	public void addPages() {
		ds = new DataSourcePage(selection);
		addPage(ds);
		ts = new TableDetailSettingPage(selection);
		addPage(ts);
		gcpp = new GenCodePathPage(selection);
		addPage(gcpp);

	}

	/**
	 * This method is called when 'Finish' button is pressed in the wizard. We
	 * will create an operation and run it using wizard as execution context.
	 */
	public boolean performFinish() {
		Table t = ts.getTable();
		Map<String, Object> param = new HashMap<String, Object>();// 模板model
		List<ColumnWrap> list = new ArrayList<ColumnWrap>();
		int len = t.getItemCount();
		for (int i = 0; i < len; i++) {
			TableItem it = t.getItem(i);
			ColumnWrap col = (ColumnWrap) it.getData();
			if(col.getColumn_key().equals("PRI"))
				param.put("pkCol", col);
			TctConsole.printLog(col.toString());
			list.add(col);

		}
		
		param.put("list", list);// 设置详细列设置集合
		final boolean[] gen = gcpp.getGen();
		String name = gcpp.getJavaName().getText();
		final String container = gcpp.getActionPath().getText();
		final String serviceContainer = gcpp.getServicePath().getText();
		final String daoContainer = gcpp.getDaoPath().getText();
		final String domainContainer = gcpp.getDomainPath().getText();
		final String viewContainer = gcpp.getViewPath().getText();
		final String module = name;
		final String controller = name.substring(0,1).toUpperCase().concat(name.substring(1)) + "Controller.java";
		final String service = name.substring(0,1).toUpperCase().concat(name.substring(1))  + "Service.java";
		final String serviceimpl = name.substring(0,1).toUpperCase().concat(name.substring(1))  + "ServiceImpl.java";
		final String dao = name.substring(0,1).toUpperCase().concat(name.substring(1))  + "Mapper.java";
		final String daoimpl = name.substring(0,1).toUpperCase().concat(name.substring(1))  + "Mapper.xml";
		final String entity = name.substring(0,1).toUpperCase().concat(name.substring(1))  + "Entity.java";
		final String query = name.substring(0,1).toUpperCase().concat(name.substring(1))  + "Query.java";
		final String view = name.substring(0,1).toUpperCase().concat(name.substring(1))  + "Index.jsp";
		String pkg = "";
		String defaultPkg="";
		if (gen[0]) {
			pkg = "";
			if (container.indexOf("src/main/java") > 0) {
				pkg = container.substring(container.indexOf("src/main/java") + 14).replace('/', '.');
				if (pkg.length() > 0){
					pkg = pkg + ".";
					defaultPkg = pkg.substring(0, pkg.indexOf("web")-1);
				}
				
			}
			param.put("controllerPkg", pkg.concat(module));
		}
		if (gen[1] || gen[2]) {
			pkg = "";
			if (serviceContainer.indexOf("src/main/java") > 0) {
				pkg = serviceContainer.substring(serviceContainer.indexOf("src/main/java") + 14).replace('/', '.');
				if (pkg.length() > 0){
					pkg = pkg + ".";
					defaultPkg = pkg.substring(0, pkg.indexOf("service")-1);
				}
			}
			param.put("servicePkg", pkg.concat(module));
		}
		if (gen[3] || gen[4]) {
			pkg = "";
			if (daoContainer.indexOf("src/main/java") > 0) {
				pkg = daoContainer.substring(daoContainer.indexOf("src/main/java") + 14).replace('/', '.');
				if (pkg.length() > 0){
					pkg = pkg + ".";
					defaultPkg = pkg.substring(0, pkg.indexOf("mapper")-1);
				}
			}
			param.put("daoPkg", pkg.concat(module));
		}
		if (gen[5] || gen[6]) {
			pkg = "";
			if (domainContainer.indexOf("src/main/java") > 0) {
				pkg = domainContainer.substring(domainContainer.indexOf("src/main/java") + 14).replace('/', '.');
				if (pkg.length() > 0){
					pkg = pkg + ".";
					defaultPkg = pkg.substring(0, pkg.indexOf("domain")-1);
				}
			}
			param.put("domainPkg", pkg.concat(module));
		}
 		param.put("defaultPkg", defaultPkg.length()>0?defaultPkg:module);
		param.put("name", name);// 设置表名用于模板里的java文件package：com.bjtct.oom.mms.module.submodule

		String table = dset.get("selectTable");
		refreshAutoGenData(table);
		param.put("table", table);// 设置对应的表
		String showStyle = gcpp.getShowStyle();
		param.put("showStyle", showStyle);// 设置显示风格,风格不同生成的方法不同。
		TctConsole.printLog("showStyle : "+showStyle);
		final Map<String, Object> o = param;

		IRunnableWithProgress op = new IRunnableWithProgress() {
			public void run(IProgressMonitor monitor) throws InvocationTargetException {
				try {

					if (gen[0]) {
						doFinish(module, controller, "Controller.ftl", container, o, monitor);
					}

					if (gen[1]) {
						doFinish(module, service, "IService.ftl", serviceContainer, o, monitor);
					}
					if (gen[2]) {
						doFinish(module, serviceimpl, "Service.ftl", serviceContainer, o, monitor);
					}

					if (gen[3]) {
						doFinish(module, dao, "IDao.ftl", daoContainer, o, monitor);
					}
					if (gen[4]) {
						doFinish(module, daoimpl, "Dao.ftl", daoContainer, o, monitor);
					}

					if (gen[5]) {
						doFinish(module, entity, "Entity.ftl", domainContainer, o, monitor);
					}
					if (gen[6]) {
						doFinish(module, query, "Query.ftl", domainContainer, o, monitor);
					}

					if (gen[7]) {
						doFinish(module, view, "Index.ftl", viewContainer, o, monitor);
					}

				} catch (CoreException e) {
					throw new InvocationTargetException(e);
				} finally {
					monitor.done();
				}
			}
		};
		try {
			getContainer().run(true, false, op);
		} catch (InterruptedException e) {
			return false;
		} catch (InvocationTargetException e) {
			Throwable realException = e.getTargetException();
			MessageDialog.openError(getShell(), "Error", realException.getMessage());
			return false;
		}
		return true;
	}

	/**
	 * The worker method. It will find the container, create the file if missing
	 * or just replace its contents, and open the editor on the newly created
	 * file.
	 */

	private void doFinish(String module, String fname, String template, String containerPath, Map<String, Object> param,
			IProgressMonitor mo) throws CoreException {
		// create a sample file
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		IResource resource = root.findMember(new Path(containerPath));
		if (!resource.exists() || !(resource instanceof IContainer)) {
			throwCoreException(containerPath + " not exists！");
		}
		IContainer cContiner = (IContainer) resource;// java文件路径
		TctConsole.printLog("begin autogen...");
		mo.beginTask("exec gen file  ", 2);
		IFolder folder = cContiner.getFolder(new Path(module));
		if (!folder.exists()) {// 如果不存在,创建包
			folder.create(true, true, mo);
		}
		final IFile file = folder.getFile(new Path(fname));
		try {

			File tmpf = new File(root.getLocation().toOSString(), "tmp.txt");
			if (!tmpf.exists()) {
				tmpf.createNewFile();
			}
			exec(tmpf, template, param);

			InputStream stream = new FileInputStream(tmpf);
			if (file.exists()) {
				file.setContents(stream, true, true, mo);
			} else {
				file.create(stream, true, mo);
			}
			stream.close();
			tmpf.delete();
			TctConsole.printLog("autogen : " + fname);

		} catch (Exception e) {
			throwCoreException(e.getMessage());
		}
		mo.worked(1);
		/*
		 * getShell().getDisplay().asyncExec(new Runnable() { public void run()
		 * { IWorkbenchPage page =
		 * PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
		 * try { IDE.openEditor(page, file, true); } catch (PartInitException e)
		 * { } } });
		 */
		TctConsole.printLog("autogen files end ! ");
		mo.worked(1);
	}

	private void exec(File target, String template, Map<String, Object> param) throws IOException, TemplateException {
		Template temp = cfg.getTemplate(template);
		BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(target), "UTF-8"));
		temp.process(param, out);
		out.close();
	}

	private void refreshAutoGenData(String table) {
		try {
			dset.load("Tct.xml");
		} catch (IOException e) {
			e.printStackTrace();
		}
		String[] genedTable = dset.getArray("autogened");
		if (null == genedTable||genedTable.length==0) {
			String[] newGened = new String[] { table };
			dset.put("autogened", newGened);
		} else {
				boolean exists = false;
			  for(int i=0;i<genedTable.length;i++){
				  if(genedTable[i].equals(table)){
					  exists = true;
					  break;
				  }
			  }
			  if(!exists){
				  String[] newGened = new String[genedTable.length + 1];
					System.arraycopy(genedTable, 0, newGened, 0, genedTable.length);
					newGened[newGened.length - 1] = table;
					dset.put("autogened", newGened);
			  }		
			 
		}

		try {
			dset.save("Tct.xml");
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	private void throwCoreException(String message) throws CoreException {
		IStatus status = new Status(IStatus.ERROR, "com.bjtct.plugin.autogen", IStatus.OK, message, null);
		throw new CoreException(status);
	}

	/**
	 * We will accept the selection in the workbench to see if we can initialize
	 * from it.
	 * 
	 * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection)
	 */
	public void init(IWorkbench workbench, IStructuredSelection selection) {
		this.selection = selection;
	}
}